home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16.lha / Python-1.6 / Lib / Python1.6 / quopri.py < prev    next >
Encoding:
Python Source  |  2000-02-04  |  3.4 KB  |  150 lines

  1. #! /usr/bin/env python
  2.  
  3. """Conversions to/from quoted-printable transport encoding as per RFC-1521."""
  4.  
  5. # (Dec 1991 version).
  6.  
  7. ESCAPE = '='
  8. MAXLINESIZE = 76
  9. HEX = '0123456789ABCDEF'
  10.  
  11. def needsquoting(c, quotetabs):
  12.     """Decide whether a particular character needs to be quoted.
  13.  
  14.     The 'quotetabs' flag indicates whether tabs should be quoted."""
  15.     if c == '\t':
  16.         return not quotetabs
  17.     return c == ESCAPE or not(' ' <= c <= '~')
  18.  
  19. def quote(c):
  20.     """Quote a single character."""
  21.     if c == ESCAPE:
  22.         return ESCAPE * 2
  23.     else:
  24.         i = ord(c)
  25.         return ESCAPE + HEX[i/16] + HEX[i%16]
  26.  
  27. def encode(input, output, quotetabs):
  28.     """Read 'input', apply quoted-printable encoding, and write to 'output'.
  29.  
  30.     'input' and 'output' are files with readline() and write() methods.
  31.     The 'quotetabs' flag indicates whether tabs should be quoted."""
  32.     while 1:
  33.         line = input.readline()
  34.         if not line: break
  35.         new = ''
  36.         last = line[-1:]
  37.         if last == '\n': line = line[:-1]
  38.         else: last = ''
  39.         prev = ''
  40.         for c in line:
  41.             if needsquoting(c, quotetabs):
  42.                 c = quote(c)
  43.             if len(new) + len(c) >= MAXLINESIZE:
  44.                 output.write(new + ESCAPE + '\n')
  45.                 new = ''
  46.             new = new + c
  47.             prev = c
  48.         if prev in (' ', '\t'):
  49.             output.write(new + ESCAPE + '\n\n')
  50.         else:
  51.             output.write(new + '\n')
  52.  
  53. def decode(input, output):
  54.     """Read 'input', apply quoted-printable decoding, and write to 'output'.
  55.  
  56.     'input' and 'output' are files with readline() and write() methods."""
  57.     new = ''
  58.     while 1:
  59.         line = input.readline()
  60.         if not line: break
  61.         i, n = 0, len(line)
  62.         if n > 0 and line[n-1] == '\n':
  63.             partial = 0; n = n-1
  64.             # Strip trailing whitespace
  65.             while n > 0 and line[n-1] in (' ', '\t'):
  66.                 n = n-1
  67.         else:
  68.             partial = 1
  69.         while i < n:
  70.             c = line[i]
  71.             if c <> ESCAPE:
  72.                 new = new + c; i = i+1
  73.             elif i+1 == n and not partial:
  74.                 partial = 1; break
  75.             elif i+1 < n and line[i+1] == ESCAPE:
  76.                 new = new + ESCAPE; i = i+2
  77.             elif i+2 < n and ishex(line[i+1]) and ishex(line[i+2]):
  78.                 new = new + chr(unhex(line[i+1:i+3])); i = i+3
  79.             else: # Bad escape sequence -- leave it in
  80.                 new = new + c; i = i+1
  81.         if not partial:
  82.             output.write(new + '\n')
  83.             new = ''
  84.     if new:
  85.         output.write(new)
  86.  
  87. def ishex(c):
  88.     """Return true if the character 'c' is a hexadecimal digit."""
  89.     return '0' <= c <= '9' or 'a' <= c <= 'f' or 'A' <= c <= 'F'
  90.  
  91. def unhex(s):
  92.     """Get the integer value of a hexadecimal number."""
  93.     bits = 0
  94.     for c in s:
  95.         if '0' <= c <= '9':
  96.             i = ord('0')
  97.         elif 'a' <= c <= 'f':
  98.             i = ord('a')-10
  99.         elif 'A' <= c <= 'F':
  100.             i = ord('A')-10
  101.         else:
  102.             break
  103.         bits = bits*16 + (ord(c) - i)
  104.     return bits
  105.  
  106. def test():
  107.     import sys
  108.     import getopt
  109.     try:
  110.         opts, args = getopt.getopt(sys.argv[1:], 'td')
  111.     except getopt.error, msg:
  112.         sys.stdout = sys.stderr
  113.         print msg
  114.         print "usage: quopri [-t | -d] [file] ..."
  115.         print "-t: quote tabs"
  116.         print "-d: decode; default encode"
  117.         sys.exit(2)
  118.     deco = 0
  119.     tabs = 0
  120.     for o, a in opts:
  121.         if o == '-t': tabs = 1
  122.         if o == '-d': deco = 1
  123.     if tabs and deco:
  124.         sys.stdout = sys.stderr
  125.         print "-t and -d are mutually exclusive"
  126.         sys.exit(2)
  127.     if not args: args = ['-']
  128.     sts = 0
  129.     for file in args:
  130.         if file == '-':
  131.             fp = sys.stdin
  132.         else:
  133.             try:
  134.                 fp = open(file)
  135.             except IOError, msg:
  136.                 sys.stderr.write("%s: can't open (%s)\n" % (file, msg))
  137.                 sts = 1
  138.                 continue
  139.         if deco:
  140.             decode(fp, sys.stdout)
  141.         else:
  142.             encode(fp, sys.stdout, tabs)
  143.         if fp is not sys.stdin:
  144.             fp.close()
  145.     if sts:
  146.         sys.exit(sts)
  147.  
  148. if __name__ == '__main__':
  149.     test()
  150.